package org.dromara.business.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.business.domain.AppUser;
import org.dromara.business.domain.bo.AppUserBo;
import org.dromara.business.domain.vo.AppUserVo;
import org.dromara.business.mapper.AppUserMapper;
import org.dromara.business.request.BindParentUserRequest;
import org.dromara.business.request.BindUserRequest;
import org.dromara.business.service.AppUserService;
import org.dromara.business.thirdparty.InviteCodeService;
import org.dromara.common.core.domain.model.AppLoginUser;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.satoken.utils.LoginHelper;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;

@Slf4j
@Service
@RequiredArgsConstructor
public class AppUserServiceImpl implements AppUserService {

    private final AppUserMapper baseMapper;
    private final InviteCodeService inviteCodeService;

    /**
     * 查询钱包用户
     *
     * @param id 主键
     * @return 钱包用户
     */
    @Override
    public AppUserVo queryById(Long id){
        return baseMapper.selectVoById(id);
    }

    /**
     * 分页查询钱包用户列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return 钱包用户分页列表
     */
    @Override
    public TableDataInfo<AppUserVo> queryPageList(AppUserBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<AppUser> lqw = buildQueryWrapper(bo);
        Page<AppUserVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        if (CollUtil.isNotEmpty(result.getRecords())) {
            for (AppUserVo record : result.getRecords()) {
                if (record.getSpreadId() != null) {
                    AppUser parentUser = getById(record.getSpreadId());
                    if (parentUser != null) {
                        record.setParentWalletAddress(parentUser.getWalletAddress());
                    }
                }
            }
        }
        return TableDataInfo.build(result);
    }

    /**
     * 查询符合条件的钱包用户列表
     *
     * @param bo 查询条件
     * @return 钱包用户列表
     */
    @Override
    public List<AppUserVo> queryList(AppUserBo bo) {
        LambdaQueryWrapper<AppUser> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    @Override
    public AppUser getById(Long userId) {
        return baseMapper.selectById(userId);
    }

    private LambdaQueryWrapper<AppUser> buildQueryWrapper(AppUserBo bo) {
        LambdaQueryWrapper<AppUser> lqw = Wrappers.lambdaQuery();
        lqw.orderByAsc(AppUser::getId);
        lqw.eq(bo.getSpreadId() != null, AppUser::getSpreadId, bo.getSpreadId());
        lqw.eq(bo.getLevel() != null, AppUser::getLevel, bo.getLevel());
        lqw.eq(StringUtils.isNotBlank(bo.getWalletAddress()), AppUser::getWalletAddress, bo.getWalletAddress());
        lqw.eq(StringUtils.isNotBlank(bo.getStatus()), AppUser::getStatus, bo.getStatus());
        lqw.eq(bo.getTotalStaked() != null, AppUser::getTotalStaked, bo.getTotalStaked());
        lqw.eq(bo.getTotalEarnings() != null, AppUser::getTotalEarnings, bo.getTotalEarnings());
        lqw.eq(bo.getBindStatus() != null, AppUser::getBindStatus, bo.getBindStatus());
        return lqw;
    }

    @Override
    public Boolean bindUser(BindUserRequest bindUserRequest) {
        if (checkWalletAddress(bindUserRequest.getWalletAddress())) {
            throw new ServiceException("钱包地址已存在");
        }
        AppUser appUser = new AppUser();
        appUser.setWalletAddress(bindUserRequest.getWalletAddress());
        appUser.setCreateTime(new Date());
//        String invitationCode = inviteCodeService.generateInviteCode(user.getId());
//        while (existsInviteCode(invitationCode)) {
//            invitationCode = inviteCodeService.generateInviteCode(user.getId());
//        }
//        user.setInvitationCode(invitationCode);
        return baseMapper.insert(appUser) > 0;
    }
//    private Boolean existsInviteCode(String inviteCode) {
//        LambdaQueryWrapper<AppUser> query = Wrappers.lambdaQuery(AppUser.class)
//            .eq(AppUser::getInvitationCode, inviteCode);
//        return baseMapper.selectCount(query) > 0;
//    }

    @Override
    public Boolean checkWalletAddress(String address) {
        return baseMapper.exists(Wrappers.lambdaQuery(AppUser.class)
            .eq(AppUser::getWalletAddress, address));
    }

    @Override
    public AppUser getAppUserByAddress(String address) {
        return baseMapper.selectOne(Wrappers.lambdaQuery(AppUser.class)
            .eq(AppUser::getWalletAddress, address));
    }

    @Override
    public void bindParentUser(BindParentUserRequest request) {
        if (StrUtil.isNotEmpty(request.getWalletAddress())) {
            AppUser parentUser = getAppUserByAddress(request.getWalletAddress());
            if (parentUser == null) {
                throw new ServiceException("上级钱包地址不存在");
            }
            AppLoginUser loginUser = LoginHelper.getAppLoginUser();
            AppUser selfUser = baseMapper.selectById(loginUser.getUserId());
            if (StrUtil.equals(selfUser.getWalletAddress(), request.getWalletAddress())) {
                throw new ServiceException("上级钱包地址不能绑定自己的");
            }
            if (selfUser.getSpreadId() != null || selfUser.getBindStatus() == 1) {
                throw new ServiceException("用户已绑定上级钱包地址");
            }
            AppUser appUser = new AppUser();
            appUser.setId(loginUser.getUserId());
            appUser.setSpreadId(parentUser.getId());
            appUser.setBindStatus(1);
            baseMapper.updateById(appUser);
        } else {
            if (request.getBindStatus() == 1) {
                AppLoginUser loginUser = LoginHelper.getAppLoginUser();
                AppUser appUser = new AppUser();
                appUser.setId(loginUser.getUserId());
                appUser.setBindStatus(1);
                baseMapper.updateById(appUser);
            }
        }
    }
}
